package com.changgou.order.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

/**
 * Created by zhangyuhong
 * Date:2020/5/17
 *
 * 权限认证用的
 */
@Configuration
@EnableResourceServer  //表示资源服务器  基本上每一个微服务都是一个微服务
//表达式时间方法级别的安全性:prePostEnabled:4个注解可用@PreAuthorize,@PostAuthorize,@PostFilter,@PreFilter
//securedEnabled:开启@Secured 注解过滤权限
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)  //开启注解
//Spring Security默认是禁用注解的，要想开启注解， 需要在继承
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    //公钥
    private static final String PUBLIC_KEY = "public.key";

    //TokenStore:一个抽象类,用来保存token
    /***
     * 定义JwtTokenStore
     * @param jwtAccessTokenConverter
     * @return
     * 这是给源码用的,也就是继承的  ResourceServerConfigurerAdapter
     */
    @Bean
    public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
        return new JwtTokenStore(jwtAccessTokenConverter);
    }


    /***
     * 定义JJwtAccessTokenConverter
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setVerifierKey(getPubKey());  //要公钥  内部会自动完成token的校验
        return converter;
    }

    /**
     * 获取非对称加密公钥 Key
     * @return 公钥 Key
     */
    private String getPubKey() {
        Resource resource = new ClassPathResource(PUBLIC_KEY);
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
            BufferedReader br = new BufferedReader(inputStreamReader);
            return br.lines().collect(Collectors.joining("\n"));
        } catch (IOException ioe) {
            return null;
        }
    }

    /***
     * Http安全配置，对每个到达系统的http请求链接进行校验  和xml的配置一样的  就是放行那行东西,需要哪些权限
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        //假设所有的请求必须要经过认证之后才能访问
        http.authorizeRequests()   //授权请求
                .anyRequest().  //除了/user/add的其他请求,权限的话是下面那一句
                authenticated();    //其他地址需要认证授权
    }
}
